# Copyright 2005 Nigel Sim <nigel.sim@jcu.edu.au>
# This file is part of Bibus, a bibliographic database that can
# work together with OpenOffice.org to generate bibliographic indexes.
#
# Bibus is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Bibus is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Bibus; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# BibTeX format
# from http://en.wikipedia.org/wiki/BibTeX
#
from __future__ import generators		# to be removed in python 2.3
import BIB

class importRef(object):
	"""Class is iterable. Return records one by one with None for the id (first field)."""
 	Type={
	'article':'ARTICLE',
	'book':'BOOK',
	'booklet':'BOOKLET',
	'conference':'CONFERENCE',
	'inbook':'INBOOK',
	'incollection':'INCOLLECTION',
	'inproceedings':'INPROCEEDINGS',
	'manual':'MANUAL',
	'mastersthesis':'MASTERTHESIS',
	'misc':'MISC',
	'phdthesis':'PHDTHESIS',
	'proceedings':'PROCEEDINGS',
	'techreport':'TECHREPORT',
	'unpublished':'UNPUBLISHED'}

	"""return a list of the record fields using
	('Identifier', 'Bibliographic_Type', 'Address', 'Annote', 'Author', 'Booktitle', 'Chapter', 'Edition', 		'Editor','Howpublished', 'Institution', 'Journal', 'Month', 'Note', 'Number', 'Organizations', 'Pages', 'Publisher',
	'School','Series', 'Title', 'Report_Type', 'Volume', 'Year', 'URL', 'Custom1', 'Custom2', 'Custom3', 'Custom4', 'Custom5', 		'ISBN','Abstract')"""
	Fields={
	'address':3,
	'annote':4,
	'annotate':4,
	'author':5,
	'booktitle':6,
	'chapter':7,
	'edition':8,
	'editor':9,
	'howpublished':10,
	'institution':11,
	'journal':12,
	'month':13,
	'note':14,
	'number':15,
	'organization':16,
	'pages':17,
	'page':17,
	'publisher':18,
	'school':19,
	'series':20,
	'title':21,
	'type':22,
	'volume':23,
	'year':24,
	'url':25,
	'doi':26,
	'location':27,
	'lccn':27,
	'keywords':28,
	'day':29,
	'issn':31,
	'isbn':31,
	'abstract':32,
	'text':14}

	def __init__(self,infile):
		self.infile = infile	# must be a file type. Need a readline() function.
		self.lookups = {}

	def __iter__(self):
		"""Generator of records. for record in <instance>: ... """
		name = None

		line = self.infile.readline()
		stack = []
		haveEntry = False
		haveName = False
		chars = ''
		while line != '':
#			print line
			line = ' '+line.strip()
			for l in line:
				if l == '@' and haveEntry == False:
					haveEntry = False
#					print "Found start of entry"
					chars = ''
				elif l =='\r' or l == '\n':
					continue # Do nothing
				elif l == ',' and haveName == False:
					name = "" # Reset the name if we find a comma, which is a field seperator
					chars = ''
				elif l == ',' and haveName == True and len(stack) == 1:
#					print "Have property"
					self.property(name, chars)
					chars = ''
					name = ''
					haveName = False
				elif l == '{' and not haveEntry:
					self.startEntry(chars)
					haveEntry = True
					haveName = False
					chars = ''
					name = ''
					
					stack.append(l)
#					print "Append ",len(stack)
				elif ( (l == '"' and stack[len(stack)-1] != l) or l == '{' ) and haveEntry and haveName and len(stack)>0:
#					record[index] = ""
#					print "Start of value"
					stack.append(l)
					if len(stack)>2:
						chars += l
#					print "Append ",len(stack)
				elif ((l == '"' and stack[len(stack)-1] == l) or l == '}') and haveEntry and haveName and len(stack)>1:
#					print "End of value"
					if len(stack)>2:
						chars += l
					stack.pop()

				elif l == '=' and haveName == False:
#					print "Found assignment", chars
#					index = self.Fields[name.strip().lower()]
					haveName = True
					name = chars
					chars = ''
				elif l == '}':
					stack.pop()
#					print "POP ",len(stack)
					if len(stack) == 0:
						if haveName: # clean up outstanding entries
							self.property(name, chars)
						entry = self.endEntry()
						if entry != None:
							yield entry
						haveEntry = False
				else:
					chars = chars + l
				#else:
				#	print "uh oh"
			line = self.infile.readline()

	def startEntry(self, type):
		"""
		The start of an entry was found. it was in the form
		@TYPE{
		"""
#		print "startEntry(%s)"%type
		if type.lower() == 'string':
			self.stringType = True
		else:
			self.stringType = False
			self.record  = []
			for i in range(33):
				self.record.append(None)
			self.record[2] = BIB.BIBLIOGRAPHIC_TYPE[self.Type[type.lower()]] # Change the BibTeX type string to a Bibus type
		return
	def endEntry(self):
		"""
		The final close bracket was discovered and this entry is done
		"""
#		print "endEntry"
		if self.stringType:
			return None
		else:
			for i in range(33):
				if i > 0 and self.record[i] == None:
					self.record[i] = ''
			return self.record
		return
	def property(self, key, value):
		"""
		A key value pair was discovered within the entry.
		"""
#		print "property(%s, %s)"%(key, value)
		value = value.strip()
#		if (value[0] == '{' and value[-1] == '}') or (value[0] == '\'' and value[-1] == '\'') or (value[0] == '"' and value[-1] == '"'):
#			value = value.strip()[1:-1]
		key = key.strip().lower()
		
		if self.stringType:
			self.lookups[key] = value
#			print key, value
		else:
			key = key.strip().lower()
			if self.Fields.has_key(key):
				if self.lookups.has_key(value):
					value = self.lookups[value]
				if self.Fields[key] != 32 and len(value) > 255:
					value = value[0:255]
				self.record[self.Fields[key]] = value
			else:
				print "Unknown key %s"%key.strip()
		return
